package com.rickpan.service;

import com.rickpan.entity.PaymentOrder;
import com.rickpan.exception.BusinessException;
import com.rickpan.repository.PaymentOrderRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
import java.util.Random;

/**
 * 支付服务
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class PaymentService {

    private final PaymentOrderRepository orderRepository;
    private final VipSubscriptionService subscriptionService;

    /**
     * 创建支付订单
     */
    @Transactional
    public PaymentOrder createPaymentOrder(Long userId, PaymentOrder.PlanType planType) {
        String orderNo = generateOrderNo();
        BigDecimal amount = getPlanAmount(planType);

        PaymentOrder order = new PaymentOrder();
        order.setUserId(userId);
        order.setOrderNo(orderNo);
        order.setPlanType(planType);
        order.setAmount(amount);
        order.setStatus(PaymentOrder.PaymentStatus.PENDING);
        order.setPaymentMethod(PaymentOrder.PaymentMethod.ALIPAY);
        order.setExpiresAt(LocalDateTime.now().plusHours(2)); // 2小时过期

        PaymentOrder savedOrder = orderRepository.save(order);
        
        log.info("创建支付订单成功: orderNo={}, userId={}, planType={}, amount={}", 
                orderNo, userId, planType, amount);
        
        return savedOrder;
    }

    /**
     * 处理支付回调 (支付宝/微信)
     */
    @Transactional
    public void handlePaymentCallback(String orderNo, String tradeNo, String status) {
        PaymentOrder order = orderRepository.findByOrderNo(orderNo)
            .orElseThrow(() -> new BusinessException("订单不存在: " + orderNo));

        log.info("处理支付回调: orderNo={}, tradeNo={}, status={}", orderNo, tradeNo, status);

        // 检查订单状态，避免重复处理
        if (order.getStatus() == PaymentOrder.PaymentStatus.PAID) {
            log.warn("订单 {} 已经是支付成功状态，忽略重复回调", orderNo);
            return;
        }

        if ("TRADE_SUCCESS".equals(status) || "TRADE_FINISHED".equals(status)) {
            // 支付成功
            order.setStatus(PaymentOrder.PaymentStatus.PAID);
            order.setTradeNo(tradeNo);
            order.setPaidAt(LocalDateTime.now());
            orderRepository.save(order);

            try {
                // 创建VIP订阅
                subscriptionService.createSubscription(
                    order.getUserId(),
                    order.getPlanType(),
                    order.getId()
                );
                
                log.info("支付成功，已创建VIP订阅: orderNo={}, userId={}", orderNo, order.getUserId());
            } catch (Exception e) {
                log.error("创建VIP订阅失败: orderNo={}", orderNo, e);
                // 注意：这里不抛出异常，避免影响支付回调确认
                // 可以通过定时任务或手动处理来补偿
            }
        } else if ("TRADE_FAILED".equals(status) || "TRADE_CLOSED".equals(status)) {
            // 支付失败
            order.setStatus(PaymentOrder.PaymentStatus.FAILED);
            order.setTradeNo(tradeNo);
            orderRepository.save(order);
            
            log.info("支付失败: orderNo={}, status={}", orderNo, status);
        }
    }

    /**
     * 手动确认支付 (管理员操作)
     */
    @Transactional
    public void manualConfirmPayment(String orderNo, String remark) {
        PaymentOrder order = orderRepository.findByOrderNo(orderNo)
            .orElseThrow(() -> new BusinessException("订单不存在: " + orderNo));

        if (order.getStatus() == PaymentOrder.PaymentStatus.PAID) {
            throw new BusinessException("订单已经支付，不能重复确认");
        }

        order.setStatus(PaymentOrder.PaymentStatus.PAID);
        order.setPaymentMethod(PaymentOrder.PaymentMethod.MANUAL);
        order.setPaidAt(LocalDateTime.now());
        order.setRemark(remark);
        orderRepository.save(order);

        // 创建VIP订阅
        subscriptionService.createSubscription(
            order.getUserId(),
            order.getPlanType(),
            order.getId()
        );

        log.info("手动确认支付成功: orderNo={}, remark={}", orderNo, remark);
    }

    /**
     * 取消订单
     */
    @Transactional
    public void cancelOrder(String orderNo) {
        PaymentOrder order = orderRepository.findByOrderNo(orderNo)
            .orElseThrow(() -> new BusinessException("订单不存在: " + orderNo));

        if (order.getStatus() != PaymentOrder.PaymentStatus.PENDING) {
            throw new BusinessException("只能取消待支付订单");
        }

        order.setStatus(PaymentOrder.PaymentStatus.CANCELLED);
        orderRepository.save(order);

        log.info("取消订单成功: orderNo={}", orderNo);
    }

    /**
     * 获取用户的订单列表
     */
    @Transactional(readOnly = true)
    public List<PaymentOrder> getUserOrders(Long userId) {
        return orderRepository.findByUserIdOrderByCreatedAtDesc(userId);
    }

    /**
     * 分页获取用户订单列表
     */
    @Transactional(readOnly = true)
    public Page<PaymentOrder> getUserOrdersPage(Long userId, Pageable pageable) {
        return orderRepository.findByUserId(userId, pageable);
    }

    /**
     * 根据订单号查询订单
     */
    @Transactional(readOnly = true)
    public Optional<PaymentOrder> getOrderByOrderNo(String orderNo) {
        return orderRepository.findByOrderNo(orderNo);
    }

    /**
     * 处理过期订单
     */
    @Transactional
    public void handleExpiredOrders() {
        List<PaymentOrder> expiredOrders = orderRepository.findExpiredPendingOrders(LocalDateTime.now());
        
        for (PaymentOrder order : expiredOrders) {
            try {
                order.setStatus(PaymentOrder.PaymentStatus.CANCELLED);
                orderRepository.save(order);
                log.info("订单过期自动取消: orderNo={}", order.getOrderNo());
            } catch (Exception e) {
                log.error("处理过期订单失败: orderNo={}", order.getOrderNo(), e);
            }
        }

        if (!expiredOrders.isEmpty()) {
            log.info("处理了 {} 个过期订单", expiredOrders.size());
        }
    }

    /**
     * 获取套餐金额
     */
    private BigDecimal getPlanAmount(PaymentOrder.PlanType planType) {
        return switch (planType) {
            case MONTHLY_VIP -> new BigDecimal("29.90");
            case YEARLY_VIP -> new BigDecimal("299.00");
        };
    }

    /**
     * 生成订单号
     */
    private String generateOrderNo() {
        return "VIP" + System.currentTimeMillis() +
               String.format("%04d", new Random().nextInt(10000));
    }

    /**
     * 获取支付统计信息
     */
    @Transactional(readOnly = true)
    public PaymentStatistics getPaymentStatistics(LocalDateTime startTime, LocalDateTime endTime) {
        List<PaymentOrder> paidOrders = orderRepository.findPaidOrdersBetween(startTime, endTime);
        
        PaymentStatistics stats = new PaymentStatistics();
        stats.setTotalOrders(paidOrders.size());
        stats.setTotalAmount(paidOrders.stream()
            .map(PaymentOrder::getAmount)
            .reduce(BigDecimal.ZERO, BigDecimal::add));
        
        long monthlyCount = paidOrders.stream()
            .filter(order -> order.getPlanType() == PaymentOrder.PlanType.MONTHLY_VIP)
            .count();
        long yearlyCount = paidOrders.stream()
            .filter(order -> order.getPlanType() == PaymentOrder.PlanType.YEARLY_VIP)
            .count();
            
        stats.setMonthlyVipCount(monthlyCount);
        stats.setYearlyVipCount(yearlyCount);
        
        return stats;
    }

    /**
     * 支付统计信息
     */
    public static class PaymentStatistics {
        private int totalOrders;
        private BigDecimal totalAmount;
        private long monthlyVipCount;
        private long yearlyVipCount;

        // Getters and Setters
        public int getTotalOrders() { return totalOrders; }
        public void setTotalOrders(int totalOrders) { this.totalOrders = totalOrders; }

        public BigDecimal getTotalAmount() { return totalAmount; }
        public void setTotalAmount(BigDecimal totalAmount) { this.totalAmount = totalAmount; }

        public long getMonthlyVipCount() { return monthlyVipCount; }
        public void setMonthlyVipCount(long monthlyVipCount) { this.monthlyVipCount = monthlyVipCount; }

        public long getYearlyVipCount() { return yearlyVipCount; }
        public void setYearlyVipCount(long yearlyVipCount) { this.yearlyVipCount = yearlyVipCount; }
    }
}